package ae.pcfc.etks.online.web.controller.user.general.service;

/* $Id: UserPersonController 
 * Copyright (C) 2011, Trakhees
 *  
 *  History
 *
 * Date  			Author 					Remarks
 * -------------------------------------------------------------
 * April 13, 2011 	Neha_Chauhan 	        Created
 *
 */

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

import ae.pcfc.etks.online.common.ConstantsCommon;
import ae.pcfc.etks.online.common.ConstantsCommon.WFProcessType;
import ae.pcfc.etks.online.common.delegate.ClientRegistrationDelegate;
import ae.pcfc.etks.online.common.delegate.ServiceDelegate;
import ae.pcfc.etks.online.common.delegate.UserDelegate;
import ae.pcfc.etks.online.common.exception.DuplicateServiceRequestException;
import ae.pcfc.etks.online.common.util.CommonUtils;
import ae.pcfc.etks.online.common.vo.AppMetaDataDetailVO;
import ae.pcfc.etks.online.common.vo.ServiceAttributesVO;
import ae.pcfc.etks.online.common.vo.ServiceVO;
import ae.pcfc.etks.online.web.ConstantsAdmin;
import ae.pcfc.etks.online.web.PageType;
import ae.pcfc.etks.online.web.ViewPath;
import ae.pcfc.etks.online.web.ViewUtils;
import ae.pcfc.etks.online.web.common.Constants;
import ae.pcfc.etks.online.web.controller.BaseController;
import ae.pcfc.etks.online.web.controller.user.general.person.UserPersonController;
import ae.pcfc.etks.online.web.model.Service;
import ae.pcfc.etks.online.web.model.UserService;
import ae.pcfc.etks.online.web.util.SecurityUtils;

/**
 * Controller that handles all {@link UserPersonController}-related requests,
 * i.e.: all requests for /user/general/service/*
 * 
 * @author Neha Chauhan
 */

@Controller
@RequestMapping(ViewPath.USER_SERVICE)
@SessionAttributes("serviceRegister")
public class UserServiceController extends BaseController{

	private UserDelegate userDelegate;

	@Resource(name = "userDelegate")
	public void setUserDelegate(UserDelegate userDelegate) {
		this.userDelegate = userDelegate;
	}

	private ServiceDelegate serviceDelegate;

	@Resource(name = "serviceDelegate")
	public void setServiceDelegate(ServiceDelegate serviceDelegate) {
		this.serviceDelegate = serviceDelegate;
	}

	private ClientRegistrationDelegate clientRegistrationDelegate;

	@Resource(name = "clientRegistrationDelegate")
	public void setClientRegistrationDelegate(ClientRegistrationDelegate clientRegistrationDelegate) {
		this.clientRegistrationDelegate = clientRegistrationDelegate;
	}


	/*
	 * @ModelAttribute(value = Constants.SERVICE_REGISTER_REFRENCE_DATA) public
	 * List<Service> populateUserServices(HttpServletRequest request,
	 * 
	 * @RequestParam(value = "id", required = false) String id) {
	 * 
	 * Object principal = SecurityContextHolder.getContext()
	 * .getAuthentication().getPrincipal(); String strUserName = null;
	 * 
	 * if (principal instanceof UserDetails) { strUserName = ((UserDetails)
	 * principal).getUsername(); } else { strUserName = principal.toString(); }
	 * 
	 * String trakheesId = null; if (strUserName != null) trakheesId =
	 * this.clientRegistrationDelegate .findTrakheesIdByUserName(strUserName);
	 * 
	 * List<ServiceVO> serviceVOs = this.serviceDelegate
	 * .findServiceByUserNameAndTrakheesId(strUserName, trakheesId);
	 * 
	 * List<Service> serviceModels = new ArrayList<Service>(); Service service;
	 * for (ServiceVO serviceVO : serviceVOs) { service = new Service();
	 * getMapper().map(serviceVO, service);
	 * serviceModels.add(service); }
	 * 
	 * // UserService userServicesInfo = UserService.createSampleData(7);
	 * 
	 * return serviceModels;// return serviceModels;
	 * 
	 * }
	 */

	/*
	 * @ModelAttribute(value = Constants.USER_SERVICE_VALUE_REQUEST_MODEL_KEY)
	 * public List<Service> populateUserSelectedServices(HttpServletRequest
	 * request,
	 * 
	 * @RequestParam(value = "id", required = false) String id, Model map) {
	 * 
	 * Object principal = SecurityContextHolder.getContext()
	 * .getAuthentication().getPrincipal(); String strUserName = null;
	 * 
	 * if (principal instanceof UserDetails) { strUserName = ((UserDetails)
	 * principal).getUsername(); } else { strUserName = principal.toString(); }
	 * 
	 * String trakheesId = null; if (strUserName != null) trakheesId =
	 * this.clientRegistrationDelegate.findTrakheesIdByUserName(strUserName);
	 * 
	 * List<ServiceVO> serviceVOs=
	 * this.serviceDelegate.findServiceByUserNameAndTrakheesId(strUserName,
	 * trakheesId); List<Service> serviceModels = new ArrayList<Service>();
	 * Service service; for(ServiceVO serviceVO: serviceVOs) { service = new
	 * Service(); getMapper().map(serviceVO, service);
	 * serviceModels.add(service); }
	 * 
	 * //UserService userServicesInfo = UserService.createSampleData(7);
	 * 
	 * return serviceModels;//return serviceModels;
	 * 
	 * }
	 */
	/**
	 * Custom handler for displaying the form, i.e.: GET requests for
	 * /user/general/service/ Note that this handler returns void instead of a
	 * {@link ModelAndView}, signifying a default logical view name should be
	 * selected by Spring MVC. The ui {@link Model} is supplied as a parameter
	 * to the method and populated with the new model object to be rendered.
	 * 
	 * 
	 * @see WEB-INF/jsp/user/general/service/form.jsp
	 */

	// @RequestMapping(value = "/form.htm", method = RequestMethod.GET)
	// public void form(@ModelAttribute(value =
	// Constants.USER_SERVICES_REQUEST_MODEL_KEY) UserService userServicesInfo)
	// {
	//
	// }

	@RequestMapping(value = "/show.htm", method = RequestMethod.GET)
	public void show(@ModelAttribute(value = ConstantsAdmin.USER_SERVICES_REQUEST_MODEL_KEY) UserService userServicesInfo, Model map) {

		Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		String strUserName = null;

		if (principal instanceof UserDetails) {
			strUserName = ((UserDetails) principal).getUsername();
		} else {
			strUserName = principal.toString();
		}

		String trakheesId = null;
		if (strUserName != null)
			trakheesId = this.clientRegistrationDelegate.findTrakheesIdByUserName(strUserName);

		List<ServiceVO> serviceVOs = this.serviceDelegate.findServiceByUserNameAndTrakheesId(strUserName, trakheesId);

		if (serviceVOs != null && serviceVOs.size() > 0) {
			List<Service> serviceModels = new ArrayList<Service>();
			Service service;
			for (ServiceVO serviceVO : serviceVOs) {
				service = new Service();
				getMapper().map(serviceVO, service);
				serviceModels.add(service);
			}
			map.addAttribute("serviceRegisterRefrenceData", serviceModels);
		}

	}

	@RequestMapping(params = { "next" }, method = RequestMethod.POST, value = "/show.htm")
	public String show(HttpServletRequest request, SessionStatus status,
			@ModelAttribute(value = ConstantsAdmin.USER_SERVICES_REQUEST_MODEL_KEY) @Valid UserService userServicesInfo,
			BindingResult errors, Model model) {

		boolean isNext = WebUtils.hasSubmitParameter(request, ConstantsAdmin.NEXT_BUTTON);

		if (isNext) {
			if (errors.hasErrors()) {
				Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
				String strUserName = null;

				if (principal instanceof UserDetails) {
					strUserName = ((UserDetails) principal).getUsername();
				} else {
					strUserName = principal.toString();
				}

				String trakheesId = null;
				if (strUserName != null)
					trakheesId = this.clientRegistrationDelegate.findTrakheesIdByUserName(strUserName);

				List<ServiceVO> serviceVOs = this.serviceDelegate.findServiceByUserNameAndTrakheesId(strUserName, trakheesId);

				if (serviceVOs != null && serviceVOs.size() > 0) {
					List<Service> serviceModels = new ArrayList<Service>();
					Service service;
					for (ServiceVO serviceVO : serviceVOs) {
						service = new Service();
						getMapper().map(serviceVO, service);
						serviceModels.add(service);
					}
					model.addAttribute("serviceRegisterRefrenceData", serviceModels);
				}
				return ViewUtils.DEFAULT_VIEW;
			}
		}

		model.addAttribute("serviceRegister", userServicesInfo);
		return ViewUtils.getRedirect(ViewPath.USER_SERVICE, PageType.FORM);
	}

	@RequestMapping(method = RequestMethod.GET, value = "/form.htm")
	public String form(HttpServletRequest request, Model model) {

		// request.setAttribute(Constants.SUCCESS_PARAM,
		// Constants.SUCCESS_PARAM);

		Map map = model.asMap();

		UserService userService = (UserService) map.get("serviceRegister");
		if(userService == null){
			return ViewUtils.getRedirect(ViewPath.USER_SERVICE, PageType.SHOW);
		}
		List<ServiceVO> serviceVOs = this.serviceDelegate.findServiceListByIds(userService.getServices());
		List<Service> serviceModels = new ArrayList<Service>();
		Service service;
		for (ServiceVO serviceVO : serviceVOs) {
			service = new Service();
			getMapper().map(serviceVO, service);
			serviceModels.add(service);
		}
		
		model.addAttribute("userServiceValue", serviceModels);
		// request.setAttribute("userServiceValue", serviceModels);
		return ViewUtils.DEFAULT_VIEW;
	}

	/**
	 * Custom handler for displaying the form, i.e.:POST requests for
	 * /user/general/service/form.jsp
	 * 
	 * @see #form(UserService)
	 * @see WEB-INF/jsp/user/general/service/form.jsp
	 */

	@RequestMapping(method = RequestMethod.POST, value = "/form.htm")
	public String form(HttpServletRequest request, SessionStatus status,
			HttpSession session,
			Model model,
			@ModelAttribute(value = ConstantsAdmin.USER_SERVICES_REQUEST_MODEL_KEY) @Valid UserService userServicesInfo,
			BindingResult errors) {

		boolean isSave = WebUtils.hasSubmitParameter(request, ConstantsAdmin.SAVE_BUTTON);

		Map map = model.asMap();
		List<Service> servicesList = (List<Service>) map.get("userServiceValue");

		if (isSave) {
/*			if (errors.hasErrors()) {
				return ViewUtils.DEFAULT_VIEW;
			} else {*/
				// TODO: Logic has to be reviewed.
				Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
				String strUserName = null;

				if (principal instanceof UserDetails) {
					strUserName = ((UserDetails) principal).getUsername();
				} else {
					strUserName = principal.toString();
				}

				String trakheesId = null;
				if (strUserName != null)
					trakheesId = this.clientRegistrationDelegate.findTrakheesIdByUserName(strUserName);

				List<ServiceVO> serviceVOs = this.serviceDelegate.findServiceByUserNameAndTrakheesId(strUserName, trakheesId);

				List<Service> serviceModels = new ArrayList<Service>();
				Service service;
				for (ServiceVO serviceVO : serviceVOs) {
					service = new Service();
					getMapper().map(serviceVO, service);
					serviceModels.add(service);
				}

				List<Service> serviceModelList = new ArrayList<Service>();

				for (Service service2 : serviceModels) {

					if (service2.getStrServiceID().equals(request.getParameter(service2.getStrServiceID().toString()))) {
						List<ServiceAttributesVO> attributesList = service2.getArrServiceAttributes();
						List<ServiceAttributesVO> attributesVOs = new ArrayList<ServiceAttributesVO>();
						ServiceAttributesVO serviceAttributesVO;

						for (ServiceAttributesVO attributesVO : attributesList) {

							attributesVO.setStrAttrValue(request.getParameter(attributesVO.getiAttrId().toString()));
							attributesVOs.add(attributesVO);
						}

						service2.setArrServiceAttributes(attributesVOs);

						serviceModelList.add(service2);
					}
				}

				AppMetaDataDetailVO appMetaDataVO = new AppMetaDataDetailVO();

				
				appMetaDataVO.setApplicationDate(CommonUtils.getCurrentDateAsDDMMYYYY());
				appMetaDataVO.setStrWFinitatedBy(strUserName);
				appMetaDataVO.setStrStatusDescEn(getMessageSource().getMessage("msg.workflow.status.in.progress", null, Locale.ENGLISH));
				appMetaDataVO.setStrStatusDescAr(getMessageSource().getMessage("msg.workflow.status.in.progress", null, new Locale(Constants.LOCALE_ARABIC)));
				appMetaDataVO.setStrWfStatus(ConstantsCommon.IN_PROGRESS);
				//appMetaDataVO.setStrProcessCode(ConstantsAdmin.SERVICE_REGISTER);
				appMetaDataVO.setProcessCode(WFProcessType.SERVICE_REGISTRATION);
				appMetaDataVO.setStrProcessStep(ConstantsAdmin.SERVICE_REGISTER_INITIATE);
				appMetaDataVO.setStrClientRefNo(ConstantsAdmin.SERVICE);

				List<ServiceVO> vos = new ArrayList<ServiceVO>();
				ServiceVO serviceVO;

				for (Service serviceModel : serviceModelList) {
					serviceVO = new ServiceVO();
					getMapper().map(serviceModel, serviceVO);
					vos.add(serviceVO);
				}

				String strRefNo = "";

				try {

					strRefNo = this.serviceDelegate.addServiceReq(strUserName, vos, appMetaDataVO);
				} catch (DuplicateServiceRequestException e) {

					errors.reject("error.exception.duplicateservicerequestexception", new Object[] { e.getService() },
							e.getLocalizedMessage());
					return ViewUtils.getRedirect(ViewPath.USER_SERVICE, PageType.SHOW);
				}

				status.setComplete();
				Map<String, String> paramMap = new HashMap<String, String>();
				paramMap.put(ConstantsAdmin.REFRENCE_NO, SecurityUtils.encryptQueryParam(strRefNo));

				session.setAttribute(ConstantsAdmin.SUCCESS_PARAM, ConstantsAdmin.SUCCESS_PARAM + " " + strRefNo);
				return ViewUtils.getRedirect(ViewPath.USER_SERVICE, PageType.SHOW, paramMap);

			/*}*/

		}
		return ViewUtils.getRedirect(ViewPath.USER_SERVICE, PageType.SHOW);
	}

}
